// 麻将玩法
import {ecs} from "db://oops-framework/libs/ecs/ECS";
import {pb} from "../../network/ws/proto";
import {Player} from "db://assets/script/game/player/player";
import {MjListenRubyDeskComp} from "db://assets/script/game/majiang/comp/listenComp";
import {MjDeskView} from "db://assets/script/game/majiang/view/mjDeskView";
import {Long} from "protobufjs";
import {InitMjDeskComp} from "db://assets/script/game/majiang/comp/initMjDeskComp";
import {StartMjDeskComp} from "db://assets/script/game/majiang/comp/startMjDeskComp";
import {pt} from "db://assets/script/game/player/api";
import {ChuPaiComp} from "db://assets/script/game/majiang/comp/chuPaiComp";

@ecs.register("MjEntity")
export class MjEntity extends ecs.Entity {
    // 房间信息
    deskInfo: pb.IDeskInfo
    // 房间内的玩家
    playerInfos: {
        [key: number]: pb.IPlayerInfo
    }
    // 玩家身上的所有牌
    playerCards: {
        [key: number]: pb.ITileInfo[]
    }
    // 公共房配置
    categoryConf: pb.ICategoryItem
    roundInfo: pb.IDeskRoundInfo
    protected init() {
    }

    // 初始化房间
    initDesk(info: pb.IDeskInfo, players: { [key: number]: pb.IPlayerInfo }) {
        this.deskInfo = {
            deskNo: info.deskNo,
            juShu: info.juShu,
            diFen: info.diFen,
            mjOpt: info.mjOpt
        }
        this.playerInfos = players
        this.playerCards = []
    }

    setCategoryConf(conf: pb.ICategoryItem) {
        this.categoryConf = conf
    }

    // 退出房间
    exitDesk() {
        this.deskInfo = null
        this.playerInfos = null
        this.categoryConf = null
        this.playerCards = null
        this.roundInfo = null
        // 移除 comp
        this.remove(MjListenRubyDeskComp)
        this.remove(MjDeskView)
    }

    // 根据 pos 获取玩家位置
    getPlayerOrder() {
        const list: pb.IPlayerInfo[] = []
        const keys = Object.keys(this.playerInfos)
        let found: boolean;
        for (let i = 0; i < this.deskInfo.mjOpt.playerCount; i ++ ){
            found = false
            for (const k of keys) {
                if (this.playerInfos[k].playerDeskInfo.pos == i) {
                    // 这个位置有人
                    list.push(this.playerInfos[k])
                    found = true
                    break
                }
            }
            if (!found) {
                // 没找到,这个位置没人
                list.push(null)
            }
        }
        const myShortId = Player.getInstance().model.shortId
        const index = list.findIndex(value => {
            return value && value.playerInfo.shortId === myShortId;
        })
        console.log("everyone", list)
        if (index === -1) {
            console.error("没有本人信息", myShortId)
            return []
        }
        return [...list.slice(index), ...list.slice(0, index)]
    }

    // 获取玩家节点位置
    getNodeIndexByShortId(shortId: number | Long) {
        const list = this.getPlayerOrder()
        return list.findIndex(value => {
            return value && value.playerInfo.shortId === shortId
        })
    }

    // 加入新玩家
    joinNewPlayer(newPlayer: pb.IPlayerInfo) {
        this.playerInfos[Number(newPlayer.playerInfo.shortId)] = newPlayer
    }

    // 用户退出
    playerExit(shortId: number | Long) {
        // TODO 如果游戏开始了，显示为托管状态，不退出房间
        delete this.playerInfos[Number(shortId)]
    }

    // 更新玩家牌
    updatePlayerCard(allCards: pb.IDuanPaiInfo[]) {
        for (const r of allCards) {
            // tid 不存在时，为0
            for (const card of r.allCards) {
                if (!card.tid) {
                    // tid = 0 时，protobuf不会传输
                    card.tid = 0
                }
                if (!card.index) {
                    card.index = 0
                }
            }
            // 排序
            this.playerCards[Number(r.shortId)] = r.allCards.sort((a, b) => {
                return a.tid - b.tid
            })
        }
    }

    // 更新小局信息
    updateRoundInfo(info: pb.IDeskRoundInfo) {
        this.roundInfo = info
    }

    // 是否游戏中
    isPlaying() {
        // 不是刚创建，不是小局结束，不是准备下一局
        return this.deskInfo.status !== pt.DeskStatus.created && this.deskInfo.status !== pt.DeskStatus.roundOver && this.deskInfo.status !== pt.DeskStatus.cleaned
    }

    // 是否轮到本人出牌
    isMyTurn() {
        const myShortId = Player.shortId()
        const playerInfo = this.playerInfos && this.playerInfos[myShortId] || null
        return this.roundInfo && playerInfo && playerInfo.playerDeskInfo.pos === this.roundInfo.curTurn
    }

    // 玩家 view
    getPlayerSideView(shortId: number) {
        const comp = this.get(MjDeskView)
        if (comp) {
            const view = comp.getPlayerView()
            if (view) {
                return view.getPlayerSideViewByShortId(shortId)
            }
        }
        return null
    }

    // 添加 initMjDeskComp
    addInitComp(deskInfo: pb.IDeskInfo, playerList: pb.IPlayerInfo[], conf: pb.ICategoryItem, reconnect: boolean,
                playerCards: pb.IDuanPaiInfo[], onFinish: Function, roundInfo: pb.IDeskRoundInfo) {
        const comp = new InitMjDeskComp()
        comp.deskInfo = deskInfo
        comp.playerList = playerList
        comp.categoryConf = conf
        comp.reconnect = reconnect
        comp.playerCards = playerCards
        comp.onFinish = onFinish
        comp.roundInfo = roundInfo
        comp.getNewTile(Player.shortId())
        this.add(comp)
    }

    addStartDeskComp(tile: pb.ITileInfo) {
        const comp = new StartMjDeskComp()
        comp.newTile = tile
        this.add(comp)
    }

    addListenComp() {
        const comp = new MjListenRubyDeskComp()
        this.add(comp)
    }

    addChuPaiComp(tid: pb.TileId, tileIndex: number) {
        const comp = new ChuPaiComp()
        comp.tileIndex = tileIndex
        comp.tid = tid
        this.add(comp)
    }
}